home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #9 / Amiga Plus CD - 2004 - No. 09.iso / amigaplus / tools / amigaos4_only / fracblank / source / fracblank.c < prev    next >
C/C++ Source or Header  |  2004-08-03  |  27KB  |  939 lines

  1. /*
  2. **  FracBlank - AmigaDOS 2.04 commodities utility screenblanker
  3. **
  4. **  Copyright © 1991-1995 by Olaf `Olsen' Barthel
  5. **    All Rights Reserved
  6. **
  7. **  Cosmic flame fractal code derived from xlock source code
  8. **
  9. **  Copyright © 1988-1991 by Patrick J. Naughton.
  10. */
  11.  
  12. #include <math.h>
  13. #include <stdarg.h>
  14. #include <string.h>
  15.  
  16. #include <dos/dos.h>
  17.  
  18. #include <exec/exec.h>
  19.  
  20. #include <graphics/gfxbase.h>
  21.  
  22. #include <intuition/intuition.h>
  23. #include <intuition/pointerclass.h>
  24.  
  25. #include <libraries/asl.h>
  26. #include <libraries/commodities.h>
  27.  
  28. #include <workbench/icon.h>
  29.  
  30. #include <proto/asl.h>
  31. #include <proto/commodities.h>
  32. #include <proto/dos.h>
  33. #include <proto/exec.h>
  34. #include <proto/graphics.h>
  35. #include <proto/icon.h>
  36. #include <proto/intuition.h>
  37. #include <proto/keymap.h>
  38. #include <proto/utility.h>
  39.  
  40. #include "Frac.h"
  41. #include "FracBlank.h"
  42.  
  43. // Some useful signals
  44.  
  45. #define SIG_CX         (1L << CxPort->mp_SigBit)
  46. //define SIG_WINDOW    (1L << Window->UserPort->mp_SigBit)
  47.  
  48. // A blank pointer
  49.  
  50. APTR          Pointer;
  51. UWORD         Nothing;
  52. struct BitMap PointerBitMap;
  53.  
  54. // The current colour mode
  55.  
  56. UBYTE ColourMode;
  57.  
  58. // The main program
  59.  
  60. struct Process *MainProcess;
  61. BOOL            PopUp;
  62.  
  63. // BlankerControl data
  64.  
  65. struct Process *BlankerControlProcess;
  66.  
  67. struct Hook ScreenHook,
  68.             WindowHook;
  69.  
  70. // BlankerEntry data
  71.  
  72. struct SignalSemaphore BlankSemaphore;
  73.  
  74. // Shared library identifiers
  75.  
  76. struct Library *CxBase,
  77.                *KeymapBase;
  78.  
  79. struct UtilityBase *UtilityBase;
  80.  
  81. struct CommoditiesIFace *ICommodities;
  82. struct KeymapIFace      *IKeymap;
  83. struct UtilityIFace     *IUtility;
  84.  
  85. // Prototypes for this module
  86.  
  87. struct Library *SafeOpenLibrary(STRPTR Name, LONG Version);
  88.  
  89. STRPTR ToolString(STRPTR *Array, STRPTR Match, STRPTR Default);
  90. LONG   ToolValue(STRPTR *Array, STRPTR Match, LONG Default);
  91. ULONG  BackfillDummy(VOID);
  92. WORD   GetSeconds(STRPTR String);
  93. VOID   CloseAll(LONG ReturnCode);
  94. VOID   OpenAll(int argc, char **argv);
  95. VOID   SaveOptions(char **argv);
  96. VOID   SPrintf(STRPTR Buffer, STRPTR FormatString, ...);
  97. LONG   Atol(STRPTR Buffer);
  98. BOOL   GetModeName(ULONG Mode, STRPTR Buffer);
  99. VOID   ReportError(struct Window *Window, STRPTR Template, LONG Error);
  100. WORD   ShowRequest(struct Window *Window, STRPTR Text, STRPTR Gadgets, ...);
  101.  
  102. /* main(int argc,char **argv):
  103.  *
  104.  *  That's where all the trouble starts.
  105.  */
  106.  
  107. int main(int argc, char **argv) {
  108.  
  109.   ULONG SignalSet;
  110.   BOOL  Done = FALSE;
  111.   
  112.   // Set Defaults
  113.   
  114.   ScreenTimeout  = 60;
  115.   PatternTimeout = 60;
  116.  
  117.   MaxRecursionLevel = 40;
  118.   MaxFlamePoints    = 200;
  119.  
  120.   // Open everything we need
  121.  
  122.   OpenAll(argc,argv);
  123.  
  124.   // Go into loop waiting for messages
  125.  
  126.   do {
  127.     // Wait for a signal...
  128.     SignalSet = SIG_CX | SIG_BREAK | SIG_WAKEUP;
  129. //  if (Window) SignalSet |= SIG_WINDOW;
  130.     SignalSet = IExec->Wait(SignalSet);
  131.     // Check the commodities toolkit reply port
  132.     if (SignalSet & SIG_CX) {
  133.       CxMsg *Message;
  134.       while(Message = (CxMsg *)IExec->GetMsg(CxPort)) HandleCxMsg(Message);
  135.     }
  136.     // ^C tells the program to quit
  137.     if (SignalSet & SIG_BREAK) Done = TRUE;
  138.     // ^F tells the program to open its control panel
  139. //  if (SignalSet & SIG_WAKEUP) SetupWindow();
  140.     // If the control panel is still open,
  141.     // check for new messages.
  142. //  if (Window) Done = HandleWindowInput(SignalSet);
  143.   }
  144.   while(!Done);
  145.  
  146.   CloseAll(RETURN_OK);
  147.   
  148.   return(0);
  149.  
  150. }
  151.  
  152. /* ToolString(STRPTR *Array,STRPTR Match,STRPTR Default):
  153.  *
  154.  *  Return the matching tooltype value, if available.
  155.  *  Otherwise do with the default value.
  156.  */
  157.  
  158. STRPTR ToolString(STRPTR *Array, STRPTR Match, STRPTR Default) {
  159.  
  160.   if (Array) {
  161.     STRPTR String;
  162.     if (String = IIcon->FindToolType(Array,Match)) return(String);
  163.   }
  164.  
  165.   return(Default);
  166.  
  167. }
  168.  
  169. /* ToolValue(STRPTR *Array,STRPTR Match,LONG Default):
  170.  *
  171.  *  Return the matching tooltype value, if available.
  172.  *  Otherwise do with the default value.
  173.  */
  174.  
  175. LONG ToolValue(STRPTR *Array, STRPTR Match, LONG Default) {
  176.  
  177.   if (Array) {
  178.     STRPTR String;
  179.     if (String = IIcon->FindToolType(Array,Match)) {
  180.       LONG Result;
  181.       if (IDOS->StrToLong(String,&Result) > 0) return(Result);
  182.     }
  183.   }
  184.  
  185.   return(Default);
  186.  
  187. }
  188.  
  189. /* BackfillDummy():
  190.  *
  191.  *  A no-op backfill routine, we'll clear the screen manually.
  192.  */
  193.  
  194. ULONG BackfillDummy(VOID) { return(TRUE); }
  195.  
  196. /* GetSeconds(STRPTR String):
  197.  *
  198.  *  Calculates the number of seconds corresponding to
  199.  *  expressions such as `11:25' or `10'.
  200.  */
  201.  
  202. WORD GetSeconds(STRPTR String) {
  203.  
  204.   UBYTE  Buffer[10];
  205.   WORD   i,
  206.          Seconds;
  207.  
  208.   IExec->CopyMem(String,Buffer,9);
  209.  
  210.   Buffer[9] = 0;
  211.  
  212.   String = Buffer;
  213.  
  214.   for(i = strlen(String) - 1; i >= 0; i--) {
  215.     if (String[i] == ':') {
  216.       Seconds = Atol(&String[i + 1]);
  217.       String[i] = 0;
  218.       Seconds += 60 * Atol(String);
  219.       if (Seconds > 30 * 60) Seconds = 30 * 60;
  220.       return(Seconds);
  221.     }
  222.   }
  223.  
  224.   if ((Seconds = Atol(String)) > 30 * 60) Seconds = 30 * 60;
  225.  
  226.   return(Seconds);
  227.  
  228. }
  229.  
  230. /* CloseAll(LONG ReturnCode):
  231.  *
  232.  *  Free all resources and exit the program.
  233.  */
  234.  
  235. VOID CloseAll(LONG ReturnCode) {
  236.  
  237.   // Wait until the screen is saved
  238.  
  239.   while(Saver) IDOS->Delay(TICKS_PER_SECOND);
  240.  
  241.   if (CxBase) ShutdownCx();
  242.  
  243.   if (BlankerControlProcess) {
  244.     IExec->Forbid();
  245.     IExec->SetSignal(0,SIG_HANDSHAKE);
  246.     IExec->Signal((struct Task *)BlankerControlProcess,SIG_FINISH);
  247.     IExec->Wait(SIG_HANDSHAKE);
  248.     IExec->Permit();
  249.   }
  250.  
  251.   if (Pointer) IIntuition->DisposeObject(Pointer);
  252.  
  253. //ShutdownWindow();
  254.  
  255.   if (Colours) IExec->FreeVec(Colours);
  256.  
  257.   if (ScreenModeRequest) IAsl->FreeAslRequest(ScreenModeRequest);
  258.  
  259.   if (IKeymap)    IExec->DropInterface((struct Interface *)IKeymap);
  260.   if (KeymapBase) IExec->CloseLibrary(KeymapBase);
  261.  
  262.   if (ICommodities) IExec->DropInterface((struct Interface *)ICommodities);
  263.   if (CxBase)       IExec->CloseLibrary(CxBase);
  264.   
  265.   if (IUtility)    IExec->DropInterface((struct Interface *)IUtility);
  266.   if (UtilityBase) IExec->CloseLibrary((struct Library *)UtilityBase);
  267.  
  268.   exit(ReturnCode);
  269.  
  270. }
  271.  
  272. /* OpenAll(int argc,char **argv):
  273.  *
  274.  *  Open all resources, initialize the colour table and
  275.  *  create the Commodities interface.
  276.  */
  277.  
  278. VOID OpenAll(int argc, char **argv) {
  279.  
  280.   STRPTR *ToolTypes,
  281.           String,
  282.           Array[ARGCOUNT];
  283.  
  284.   struct RDArgs     *Args;
  285.   struct DiskObject *Icon;
  286.  
  287.   IX Expression;
  288.  
  289.   LONG Error;
  290.  
  291.   // Initialize this, the rotation code needs it
  292.  
  293.   deg45 = sin(-45.0);
  294.  
  295.   ScreenHook.h_Entry = (HOOKFUNC)BackfillDummy;
  296.   WindowHook.h_Entry = (HOOKFUNC)BackfillDummy;
  297.  
  298.   IExec->InitSemaphore(&BlankSemaphore);
  299.  
  300.   MainProcess = (struct Process *)IExec->FindTask(NULL);
  301.  
  302.   // Open the libraries we need
  303.  
  304.  
  305.   if (!(CxBase = IExec->OpenLibrary("commodities.library",50))) {
  306.     ReportError(NULL,NULL,ERR_NoCommodities);
  307.     CloseAll(RETURN_FAIL);
  308.   }
  309.   
  310.   if (!(ICommodities = (struct CommoditiesIFace *)IExec->GetInterface(CxBase,"main",1,TAG_DONE))) {
  311.     ReportError(NULL,NULL,ERR_NoCommoditiesIFace);
  312.     CloseAll(RETURN_FAIL);
  313.   }
  314.  
  315.   if (!(KeymapBase = IExec->OpenLibrary("keymap.library",50))) {
  316.     ReportError(NULL,NULL,ERR_NoKeymap);
  317.     CloseAll(RETURN_FAIL);
  318.   }
  319.  
  320.   if (!(IKeymap = (struct KeymapIFace *)IExec->GetInterface(KeymapBase,"main",1,TAG_DONE))) {
  321.     ReportError(NULL,NULL,ERR_NoKeymapIFace);
  322.     CloseAll(RETURN_FAIL);
  323.   }
  324.  
  325.   if (!(UtilityBase = (struct UtilityBase *)IExec->OpenLibrary("utility.library",50))) {
  326.     ReportError(NULL,NULL,ERR_NoKeymap);
  327.     CloseAll(RETURN_FAIL);
  328.   }
  329.  
  330.   if (!(IUtility = (struct UtilityIFace *)IExec->GetInterface((struct Library *)UtilityBase,"main",1,TAG_DONE))) {
  331.     ReportError(NULL,NULL,ERR_NoUtilityIFace);
  332.     CloseAll(RETURN_FAIL);
  333.   }
  334.  
  335.   if (!(ScreenModeRequest = (struct ScreenModeRequester *)IAsl->AllocAslRequestTags(ASL_ScreenModeRequest,
  336.                                                                                     ASLSM_DoDepth,       TRUE,
  337.                                                                                     ASLSM_PropertyFlags, NULL,
  338.                                                                                     ASLSM_PropertyMask,  DIPF_IS_DUALPF | DIPF_IS_PF2PRI | DIPF_IS_HAM | DIPF_IS_EXTRAHALFBRITE,
  339.                                                                                     ASLSM_MinDepth,      1,
  340.                                                                                     ASLSM_MaxDepth,      8,
  341.                                                                                     ASLSM_UserData,      FALSE,
  342.                                                                                     TAG_DONE))) {
  343.     ReportError(NULL,NULL,ERR_ScreenModeRequest);
  344.     CloseAll(RETURN_FAIL);
  345.   }
  346.  
  347.   // Set up a transparent window pointer
  348.  
  349.   IGraphics->InitBitMap(&PointerBitMap,2,16,1);
  350.  
  351.   PointerBitMap.Planes[0] = PointerBitMap.Planes[1] = (PLANEPTR)&Nothing;
  352.  
  353.   if (!(Pointer = IIntuition->NewObject(NULL,POINTERCLASS,
  354.                                         POINTERA_BitMap,   &PointerBitMap,
  355.                                         POINTERA_XOffset,   0,
  356.                                         POINTERA_YOffset,   0,
  357.                                         POINTERA_WordWidth, 2,
  358.                                         TAG_DONE))) {
  359.     ReportError(NULL,NULL,ERR_NoPointer);
  360.     CloseAll(RETURN_FAIL);
  361.   }
  362.  
  363.   if (!(Colours = (ColourTable *)IExec->AllocVec(sizeof(ColourTable) + 255 * sizeof(ColourEntry),MEMF_ANY | MEMF_CLEAR))) {
  364.     ReportError(NULL,NULL,ERR_NoColours);
  365.     CloseAll(RETURN_FAIL);
  366.   }
  367.  
  368.   IExec->Forbid();
  369.  
  370.   if (BlankerControlProcess = IDOS->CreateNewProcTags(NP_Name,      "« FracBlank Control Process »",
  371.                                                       NP_Priority,  100,
  372.                                                       NP_Entry,     BlankerControlEntry,
  373.                                                       NP_StackSize, 4096,
  374.                                                       NP_WindowPtr, -1,
  375.                                                       TAG_DONE)) {
  376.     IExec->SetSignal(0,SIG_HANDSHAKE);
  377.     // Wait for handshake signal
  378.     IExec->Wait(SIG_HANDSHAKE);
  379.   }
  380.  
  381.   IExec->Permit();
  382.  
  383.   if (!BlankerControlProcess) {
  384.     ReportError(NULL,NULL,ERR_NoControlProcess);
  385.     CloseAll(RETURN_FAIL);
  386.   }
  387.  
  388.   memset(Array,0,sizeof(Array));
  389.  
  390.   if (argc) {
  391.     if (!(Args = IDOS->ReadArgs("CX_PRIORITY/N/K,CX_POPKEY/K,CX_POPUP/K,BLANKSCREEN/K,SAVESCREEN/K,FRACTAL/K,COLOUR/K,DISPLAYMODE/K,DEPTH/N/K,SCREENTIMEOUT/K,PATTERNTIMEOUT/K,MAXRECURSION/N/K,MAXDOTS/N/K",(LONG *)Array,NULL))) {
  392.       IDOS->PrintFault(IDOS->IoErr(),"FracBlank");
  393.       CloseAll(RETURN_FAIL);
  394.     }
  395.     ToolTypes = NULL;
  396.     Icon      = NULL;
  397.   }
  398.   else {
  399.     struct WBStartup *Startup = (struct WBStartup *)argv;
  400.     BPTR OldDir;
  401.     Args = NULL;
  402.     OldDir = IDOS->CurrentDir(MainProcess->pr_HomeDir);
  403.     if (Icon = IIcon->GetDiskObject(Startup->sm_ArgList->wa_Name)) ToolTypes = (STRPTR *)Icon->do_ToolTypes;
  404.     else ToolTypes = NULL;
  405.     IDOS->CurrentDir(OldDir);
  406.   }
  407.  
  408.   NewBroker.nb_Pri = ToolValue(ToolTypes,"CX_PRIORITY",Array[ARG_PRIORITY] ? *(LONG *)Array[ARG_PRIORITY] : 0);
  409.  
  410.   // We'll put up a mask of qualifiers we don't want the blanker
  411.   // to stop at
  412.  
  413.   SpecialQualifier = IEQUALIFIER_REPEAT;
  414.  
  415.   // Set the Commodity popup hotkey if possible
  416.  
  417.   strcpy(HotkeyBuffer,ToolString(ToolTypes,"CX_POPKEY",Array[ARG_POPKEY] ? Array[ARG_POPKEY] : (STRPTR)"shift f1"));
  418.  
  419.   SpecialQualifier = AddQualifier(HotkeyBuffer,SpecialQualifier);
  420.  
  421.   if (Error = ICommodities->ParseIX(HotkeyBuffer,&Expression)) {
  422.     ReportError(NULL,"Invalid CX_POPKEY specification\n%s",ERR_BadFilter);
  423.     CloseAll(RETURN_FAIL);
  424.   }
  425.  
  426.   /* Determine the screen blanker hotkey. */
  427.  
  428.   strcpy(BlankScreenBuffer,ToolString(ToolTypes,"BLANKSCREEN",Array[ARG_BLANKSCREEN] ? Array[ARG_BLANKSCREEN] : (STRPTR)"shift f2"));
  429.  
  430.   SpecialQualifier = AddQualifier(BlankScreenBuffer,SpecialQualifier);
  431.  
  432.   if (Error = ICommodities->ParseIX(BlankScreenBuffer,&Expression)) {
  433.     ReportError(NULL,"Invalid BLANKSCREEN specification\n%s",ERR_BadFilter);
  434.     CloseAll(RETURN_FAIL);
  435.   }
  436.  
  437.   // Set the screen save hotkey
  438.  
  439.   strcpy(SaveScreenBuffer,ToolString(ToolTypes,"SAVESCREEN",Array[ARG_SAVESCREEN] ? Array[ARG_SAVESCREEN] : (STRPTR)"shift f3"));
  440.  
  441.   SpecialQualifier = AddQualifier(SaveScreenBuffer,SpecialQualifier);
  442.  
  443.   if (Error = ICommodities->ParseIX(SaveScreenBuffer,&Expression)) {
  444.     ReportError(NULL,"Invalid SAVESCREEN specification\n%s",ERR_BadFilter);
  445.     CloseAll(RETURN_FAIL);
  446.   }
  447.  
  448.   // Which fractal type?
  449.  
  450.   String = ToolString(ToolTypes,"FRACTAL",Array[ARG_FRACTAL] ? Array[ARG_FRACTAL] : (STRPTR)"RANDOM");
  451.  
  452.   if (IIcon->MatchToolValue(String,"REALPLANE") || IIcon->MatchToolValue(String,"REAL")) FractalType = FRACTAL_REAL_PLANE;
  453.   else {
  454.     if (IIcon->MatchToolValue(String,"COSMICFLAME") || IIcon->MatchToolValue(String,"COSMIC") || IIcon->MatchToolValue(String,"FLAME")) FractalType = FRACTAL_COSMIC_FLAME;
  455.     else FractalType = FRACTAL_RANDOM;
  456.   }
  457.  
  458.   // Which colour mode?
  459.  
  460.   String = ToolString(ToolTypes,"COLOUR",Array[ARG_COLOUR] ? Array[ARG_COLOUR] : (STRPTR)"CYCLE");
  461.  
  462.   if (IIcon->MatchToolValue(String,"STATIC")) ColourMode = COLOUR_STATIC;
  463.   else ColourMode = COLOUR_CYCLE;
  464.  
  465.   // Which display mode?
  466.  
  467.   DisplayID = INVALID_ID;
  468.  
  469.   if (String = ToolString(ToolTypes,"DISPLAYMODE",Array[ARG_DISPLAYMODE])) {
  470.     UBYTE LocalBuffer[40];
  471.     ULONG ID = INVALID_ID;
  472.     while((ID = IGraphics->NextDisplayInfo(ID)) != INVALID_ID) {
  473.       if (GetModeName(ID,LocalBuffer)) {
  474.         if (!IUtility->Stricmp(LocalBuffer,String)) {
  475.           struct DisplayInfo DisplayInfo;
  476.           if (IGraphics->GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,ID)) {
  477.             if (!(DisplayInfo.NotAvailable & ~DI_AVAIL_NOTWITHGENLOCK)) {
  478.               if (!(DisplayInfo.PropertyFlags & (DIPF_IS_DUALPF | DIPF_IS_PF2PRI | DIPF_IS_HAM | DIPF_IS_EXTRAHALFBRITE))) {
  479.                 DisplayID = ID;
  480.                 break;
  481.               }
  482.             }
  483.           }
  484.         }
  485.       }
  486.     }
  487.   }
  488.  
  489.   // Which depth?
  490.  
  491.   Depth = ToolValue(ToolTypes,"DEPTH",Array[ARG_DEPTH] ? *(LONG *)Array[ARG_DEPTH] : 0);
  492.  
  493.   if (Depth > 8) Depth = 8;
  494.   else {
  495.     if (Depth < 0) Depth = 0;
  496.   }
  497.  
  498.   // Adjust the screen timeout if possible
  499.  
  500.   ScreenTimeout = GetSeconds(ToolString(ToolTypes,"SCREENTIMEOUT",Array[ARG_SCREENTIMEOUT] ? Array[ARG_SCREENTIMEOUT] : (STRPTR)"1:00"));
  501.  
  502.   // Adjust the pattern change timeout
  503.  
  504.   PatternTimeout = GetSeconds(ToolString(ToolTypes,"PATTERNTIMEOUT",Array[ARG_PATTERNTIMEOUT] ? Array[ARG_PATTERNTIMEOUT] : (STRPTR)"1:00"));
  505.  
  506.   // Take care of the recursion level
  507.  
  508.   MaxRecursionLevel = ToolValue(ToolTypes,"MAXRECURSION",Array[ARG_MAXRECURSION] ? *(LONG *)Array[ARG_MAXRECURSION] : 40);
  509.  
  510.   if (MaxRecursionLevel < 10) MaxRecursionLevel = 10;
  511.   else {
  512.     if (MaxRecursionLevel > 100) MaxRecursionLevel = 100;
  513.   }
  514.  
  515.   // Now for the cosmic flame dots
  516.  
  517.   MaxFlamePoints = ToolValue(ToolTypes,"MAXDOTS",Array[ARG_MAXDOTS] ? *(LONG *)Array[ARG_MAXDOTS] : 20000);
  518.  
  519.   MaxFlamePoints /= 100;
  520.  
  521.   if (MaxFlamePoints < 10) MaxFlamePoints = 10;
  522.   else {
  523.     if (MaxFlamePoints > 1000) MaxFlamePoints = 1000;
  524.   }
  525.  
  526.   // Create the commodities interface
  527.  
  528.   if (Error = SetupCx()) {
  529.     if (Error != ERR_Duplicate) ReportError(NULL,NULL,Error);
  530.     if (Args) IDOS->FreeArgs(Args);
  531.     if (Icon) IIcon->FreeDiskObject(Icon);
  532.     CloseAll(RETURN_FAIL);
  533.   }
  534.  
  535.   // Pop up the control panel if necessary
  536.  
  537. //if (MatchToolValue(ToolString(ToolTypes,"CX_POPUP",Array[ARG_POPUP] ? Array[ARG_POPUP] : (STRPTR)"no"),"yes")) {
  538. //  PopUp = TRUE;
  539. //  SetupWindow();
  540. //}
  541.  
  542.   // Clean up
  543.  
  544.   if (Args) IDOS->FreeArgs(Args);
  545.  
  546.   if (Icon) IIcon->FreeDiskObject(Icon);
  547.  
  548. }
  549.  
  550. /* SaveOptions(char **argv):
  551.  *
  552.  *  Here we store the current options within the program icon.
  553.  */
  554.  
  555. VOID SaveOptions(char **argv) {
  556.  
  557.   static STRPTR KnownTypes[] = {
  558.     "CX_PRIORITY",
  559.     "CX_POPKEY",
  560.     "CX_POPUP",
  561.     "BLANKSCREEN",
  562.     "SAVESCREEN",
  563.     "FRACTAL",
  564.     "COLOUR",
  565.     "DISPLAYMODE",
  566.     "DEPTH",
  567.     "SCREENTIMEOUT",
  568.     "PATTERNTIMEOUT",
  569.     "MAXRECURSION",
  570.     "MAXDOTS"
  571.   };
  572.  
  573.   BPTR OldDir;
  574.  
  575.   struct WBStartup  *Startup = (struct WBStartup *)argv;
  576.   struct DiskObject *Icon;
  577.  
  578.   OldDir = IDOS->CurrentDir(MainProcess->pr_HomeDir);
  579.  
  580.   // Get the program icon
  581.  
  582.   if (Icon = IIcon->GetDiskObject(Startup->sm_ArgList->wa_Name)) {
  583.     STRPTR  *Types,
  584.             *NewTypes,
  585.              Data;
  586.     LONG Count = 0,
  587.          Known = sizeof(KnownTypes) / sizeof(STRPTR),Len = 0,
  588.          i;
  589.     // Count the number of tooltypes present
  590.     if (Types = (STRPTR *)Icon->do_ToolTypes) {
  591.       while(Types[Count]) Count++;
  592.     }
  593.     // Count the room required for the tooltypes to add
  594.     for(i = 0; i < Known; i++) Len += strlen(KnownTypes[i]) + 2;
  595.     // Add room for the keys
  596.     Len += (10) + (256) + (4) + (256) + (256) + (8) + (8) + (40) + (10) + (10) + (10) + (10) + (10);
  597.     // All the data will go here
  598.     if (NewTypes = (STRPTR *)IExec->AllocVec(Len + (Count + 1 + Known) * sizeof(STRPTR),MEMF_ANY | MEMF_CLEAR)) {
  599.       STRPTR *Tool = NewTypes,
  600.               String;
  601.       UBYTE   LocalBuffer[DISPLAYNAMELEN];
  602.       Data = (STRPTR)&NewTypes[Count + 1 + Known];
  603.       // CX_PRIORITY=[..]
  604.       SPrintf(Data,"CX_PRIORITY=%ld",NewBroker.nb_Pri);
  605.       *Tool++ = Data;
  606.       Data += strlen(Data) + 1;
  607.       // CX_POPKEY=[..]
  608.       SPrintf(Data,"CX_POPKEY=%s",HotkeyBuffer);
  609.       *Tool++ = Data;
  610.       Data += strlen(Data) + 1;
  611.       // CX_POPUP=[..]
  612.       SPrintf(Data,"CX_POPUP=%s",PopUp ? "yes" : "no");
  613.       *Tool++ = Data;
  614.       Data += strlen(Data) + 1;
  615.       // BLANKSCREEN=[..]
  616.       SPrintf(Data,"BLANKSCREEN=%s",BlankScreenBuffer);
  617.       *Tool++ = Data;
  618.       Data += strlen(Data) + 1;
  619.       // SAVESCREEN=[..]
  620.       SPrintf(Data,"SAVESCREEN=%s",SaveScreenBuffer);
  621.       *Tool++ = Data;
  622.       Data += strlen(Data) + 1;
  623.       // FRACTAL=[..]
  624.       switch(FractalType) {
  625.         case FRACTAL_REAL_PLANE:
  626.           String = "REALPLANE";
  627.           break;
  628.         case FRACTAL_COSMIC_FLAME:
  629.           String = "COSMICFLAME";
  630.           break;
  631.         case FRACTAL_RANDOM:
  632.           String = "RANDOM";
  633.           break;
  634.       }
  635.       SPrintf(Data,"FRACTAL=%s",String);
  636.       *Tool++ = Data;
  637.       Data += strlen(Data) + 1;
  638.       // COLOUR=[..]
  639.       switch(ColourMode) {
  640.         case COLOUR_CYCLE:
  641.           String = "CYCLE";
  642.           break;
  643.         case COLOUR_STATIC:
  644.           String = "STATIC";
  645.           break;
  646.       }
  647.       SPrintf(Data,"COLOUR=%s",String);
  648.       *Tool++ = Data;
  649.       Data += strlen(Data) + 1;
  650.       // DISPLAYMODE=[..]
  651.       if (GetModeName(DisplayID,LocalBuffer)) {
  652.         SPrintf(Data,"DISPLAYMODE=%s",LocalBuffer);
  653.         *Tool++ = Data;
  654.         Data += strlen(Data) + 1;
  655.       }
  656.       // DEPTH=[..]
  657.       SPrintf(Data,"DEPTH=%ld",Depth);
  658.       *Tool++ = Data;
  659.       Data += strlen(Data) + 1;
  660.       // SCREENTIMEOUT=[..]
  661.       SPrintf(Data,"SCREENTIMEOUT=%ld:%02ld",ScreenTimeout / 60,ScreenTimeout % 60);
  662.       *Tool++ = Data;
  663.       Data += strlen(Data) + 1;
  664.       // PATTERNTIMEOUT=[..]
  665.       SPrintf(Data,"PATTERNTIMEOUT=%ld:%02ld",PatternTimeout / 60,PatternTimeout % 60);
  666.       *Tool++ = Data;
  667.       Data += strlen(Data) + 1;
  668.       // MAXRECURSION=[..]
  669.       SPrintf(Data,"MAXRECURSION=%ld",MaxRecursionLevel);
  670.       *Tool++ = Data;
  671.       Data += strlen(Data) + 1;
  672.       // MAXDOTS=[..]
  673.       SPrintf(Data,"MAXDOTS=%ld",MaxFlamePoints * 100);
  674.       *Tool++ = Data;
  675.       // Now add the remaining old tooltypes,
  676.       // unless we already took care of them
  677.       if (Types = (STRPTR *)Icon->do_ToolTypes) {
  678.         BOOL GotIt;
  679.         while(*Types) {
  680.           GotIt = FALSE;
  681.           for(i = 0; i < Known; i++) {
  682.             if (!IUtility->Strnicmp(*Types,KnownTypes[i],strlen(KnownTypes[i]))) {
  683.               GotIt = TRUE;
  684.               break;
  685.             }
  686.           }
  687.           if (!GotIt) *Tool++ = *Types;
  688.           Types++;
  689.         }
  690.       }
  691.       // Install the new tooltypes
  692.       Icon->do_ToolTypes = (STRPTR *)NewTypes;
  693.       // Write the icon
  694. //    if (!IIcon->PutDiskObject(Startup->sm_ArgList->wa_Name,Icon)) ReportError(Window,"Error writing icon\n%s",IDOS->IoErr());
  695.       // Clean up
  696.       IExec->FreeVec(NewTypes);
  697.     }
  698. //  else ReportError(Window,NULL,ERROR_NO_FREE_STORE);
  699.     IIcon->FreeDiskObject(Icon);
  700.   }
  701. //else ReportError(Window,"Error reading icon\n%s",IoErr());
  702.  
  703.   IDOS->CurrentDir(OldDir);
  704.  
  705. }
  706.  
  707. /* SafeOpenLibrary(STRPTR Name,LONG Version):
  708.  *
  709.  *  Just like OpenLibrary, but makes sure that old
  710.  *  library versions get flushed from memory.
  711.  */
  712.  
  713. struct Library *SafeOpenLibrary(STRPTR Name, LONG Version) {
  714. /*
  715.   struct Library *Base;
  716.  
  717.   IExec->Forbid();
  718.  
  719.   if (Base = (struct Library *)IExec->FindName(&SysBase->LibList,IDOS->FilePart(Name))) {
  720.     if(Base->lib_Version < Version) IExec->RemLibrary(Base);
  721.   }
  722.  
  723.   IExec->Permit();
  724. */
  725.   return(IExec->OpenLibrary(Name,Version));
  726.  
  727. }
  728.  
  729. /* SPrintf(STRPTR Buffer,STRPTR FormatString,...):
  730.  *
  731.  *  String formatting routine, similar to sprintf().
  732.  */
  733.  
  734. VOID SPrintf(STRPTR Buffer, STRPTR FormatString, ...) {
  735.  
  736.   va_list VarArgs;
  737.  
  738.   va_start(VarArgs,FormatString);
  739.  
  740.   IUtility->VSNPrintf(Buffer,sizeof(Buffer),FormatString,VarArgs);
  741.  
  742.   va_end(VarArgs);
  743.  
  744. }
  745.  
  746. /* Atol(STRPTR Buffer):
  747.  *
  748.  *  Convert a string into a long word.
  749.  */
  750.  
  751. LONG Atol(STRPTR Buffer) {
  752.  
  753.   LONG Result;
  754.  
  755.   IDOS->StrToLong(Buffer,&Result);
  756.  
  757.   return(Result);
  758.  
  759. }
  760.  
  761. /* GetModeName(ULONG Mode,STRPTR Buffer):
  762.  *
  763.  *  This routine supplies the name for a DisplayID.
  764.  */
  765.  
  766. BOOL GetModeName(ULONG Mode, STRPTR Buffer) {
  767.  
  768.   struct NameInfo NameInfo;
  769.  
  770.   if (IGraphics->GetDisplayInfoData(NULL,(APTR)&NameInfo,sizeof(struct NameInfo),DTAG_NAME,Mode)) strcpy(Buffer,NameInfo.Name);
  771.   else {
  772.     struct DisplayInfo DisplayInfo;
  773.     if (IGraphics->GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,Mode)) {
  774.       struct DimensionInfo DimensionInfo;
  775.       if (IGraphics->GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,Mode)) {
  776.         STRPTR MonitorName;
  777.         switch(Mode & MONITOR_ID_MASK) {
  778.           case NTSC_MONITOR_ID:
  779.             MonitorName = "NTSC:";
  780.             break;
  781.           case PAL_MONITOR_ID:
  782.             MonitorName = "PAL:";
  783.             break;
  784.           case VGA_MONITOR_ID:
  785.             MonitorName = "VGA:";
  786.             break;
  787.           case A2024_MONITOR_ID:
  788.             MonitorName = "A2024:";
  789.             break;
  790.           default:
  791.             MonitorName = "";
  792.             break;
  793.         }
  794.         if (DisplayInfo.PropertyFlags & DIPF_IS_HAM) {
  795.           SPrintf(Buffer,"%s%ld × %ld HAM",MonitorName,DimensionInfo.TxtOScan.MaxX - DimensionInfo.TxtOScan.MinX + 1,DimensionInfo.TxtOScan.MaxY - DimensionInfo.TxtOScan.MinY + 1);
  796.         }
  797.         else {
  798.           SPrintf(Buffer,"%s%ld × %ld",MonitorName,DimensionInfo.TxtOScan.MaxX - DimensionInfo.TxtOScan.MinX + 1,DimensionInfo.TxtOScan.MaxY - DimensionInfo.TxtOScan.MinY + 1);
  799.         }
  800.       }
  801.       else return(FALSE);
  802.     }
  803.     else return(FALSE);
  804.   }
  805.  
  806.   return(TRUE);
  807.  
  808. }
  809.  
  810. /* ReportError(struct Window *Window,STRPTR Template,LONG Error):
  811.  *
  812.  *  Show an error message.
  813.  */
  814.  
  815. VOID ReportError(struct Window *Window, STRPTR Template, LONG Error) {
  816.  
  817.   static struct {
  818.     LONG Error;
  819.     STRPTR Code;
  820.   } Table[] = {
  821.     ERR_SystemError, "Commodities system error; out of memory",
  822.     ERR_Duplicate,   "Commodities broker already exists",
  823.     ERR_Version,     "Commodities broker version not supported",
  824.  
  825.     ERR_BadFilter, "Bad filter descriptor",
  826.     ERR_BadType,   "Bad type descriptor",
  827.  
  828.     ERR_NoIntuition,       "Could not open intuition.library v37",
  829.     ERR_NoGfx,             "Could not open graphics.library v39",
  830.     ERR_NoAsl,             "Could not open asl.library v38",
  831.     ERR_NoCommodities,     "Could not open commodities.library v50",
  832.     ERR_NoCommoditiesIFace,"Could not open commodities main interface v1",
  833.     ERR_NoUtility,         "Could not open utility.library v50",
  834.     ERR_NoUtilityIFace,    "Could not open utility main interface v1",
  835.     ERR_NoIcon,            "Could not open icon.library v37",
  836.     ERR_ScreenModeRequest, "Could not allocate screen mode requester",
  837.     ERR_NoColours,         "Could not allocate colour table; out of memory",
  838.     ERR_NoPointer,         "Could not allocate mouse pointer; out of memory",
  839.     ERR_NoControlProcess,  "Could not create mouse blanker process",
  840.     ERR_NoMsgPort,         "Could not create message port",
  841.     ERR_NoWindow,          "Could not open window",
  842.     ERR_NoKeymap,          "Could not open keymap.library v50",
  843.     ERR_NoKeymapIFace,     "Could not open keymap interface v1",
  844.     ERR_NoGTLayout,        "Could not open gtlayout.library v9",
  845.  
  846.     0,
  847.     NULL
  848.   };
  849.  
  850.   UBYTE  LocalBuffer[256];
  851.   STRPTR Buffer;
  852.   BOOL   GotIt = FALSE;
  853.   LONG   i;
  854.  
  855.   // Look for the corresponding error message.
  856.  
  857.   for(i = 0; Table[i].Error; i++) {
  858.     if (Error == Table[i].Error) {
  859.       Buffer = Table[i].Code;
  860.       GotIt = TRUE;
  861.       break;
  862.     }
  863.   }
  864.  
  865.   if (!GotIt) {
  866.     if (!IDOS->Fault(Error,"",LocalBuffer,256)) return;
  867.     Buffer = &LocalBuffer[2];
  868.   }
  869.  
  870.   if (!Template) Template = Buffer;
  871.  
  872.   if (MainProcess->pr_CLI && !Window) {
  873.     IDOS->Printf("FracBlank: ");
  874.     IDOS->Printf(Template,Buffer);
  875.     IDOS->Printf("\n");
  876.   }
  877.   else ShowRequest(Window,Template,"Continue",Buffer);
  878.  
  879. }
  880.  
  881. /* ShowRequest(struct Window *Window,STRPTR Text,STRPTR Gadgets,...):
  882.  *
  883.  *  This routine shows an easy requester. If there is just one
  884.  *  button to be pressed, the user will be able to answer it
  885.  *  by pressing any key.
  886.  */
  887.  
  888. WORD ShowRequest(struct Window *Window, STRPTR Text, STRPTR Gadgets, ...) {
  889.  
  890.   if (IntuitionBase) {
  891.     struct EasyStruct Easy;
  892.     va_list VarArgs;
  893.     LONG    i,
  894.             GadgetCount;
  895.  
  896.     for(i = GadgetCount = 0; i < strlen(Gadgets); i++) {
  897.       if (Gadgets[i] == '|') GadgetCount++;
  898.     }
  899.  
  900.     Easy.es_StructSize   = sizeof(struct EasyStruct);
  901.     Easy.es_Flags        = 0;
  902.     Easy.es_Title        = "Fractal screen blanker";
  903.     Easy.es_TextFormat   = Text;
  904.     Easy.es_GadgetFormat = Gadgets;
  905.  
  906.     if (GadgetCount) {
  907.       WORD Result;
  908. //    if (GTLayoutBase) LT_LockWindow(Window);
  909.       va_start(VarArgs,Gadgets);
  910.       Result = IIntuition->EasyRequestArgs(Window,&Easy,NULL,VarArgs);
  911.       va_end(VarArgs);
  912. //    if (GTLayoutBase) LT_UnlockWindow(Window);
  913.       return(Result);
  914.     }
  915.     else {
  916.       struct Window *ReqWindow;
  917. //    if (GTLayoutBase) LT_LockWindow(Window);
  918.       va_start(VarArgs,Gadgets);
  919.       if (ReqWindow = IIntuition->BuildEasyRequestArgs(Window,&Easy,IDCMP_RAWKEY,VarArgs)) {
  920.         ULONG IDCMP;
  921.         LONG  Result;
  922.         for(;;) {
  923.           IExec->WaitPort(ReqWindow->UserPort);
  924.           IDCMP = 0;
  925.           Result = IIntuition->SysReqHandler(ReqWindow,&IDCMP,FALSE);
  926.           if (!Result || (Result == -2 && !(IDCMP & IDCMP_RAWKEY))) break;
  927.         }
  928.         IIntuition->FreeSysRequest(ReqWindow);
  929.       }
  930.       va_end(VarArgs);
  931. //    if (GTLayoutBase) LT_UnlockWindow(Window);
  932.     }
  933.   }
  934.  
  935.   return(0);
  936.  
  937. }
  938.  
  939.